package com.mazaiting.classfile;

import com.mazaiting.util.ByteUtil;
import com.mazaiting.util.UnsignedNumberUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * 类解析工具
 *
 * @author mazaiting
 * @since 2021/8/11
 */
@Slf4j
@Data
public class ClassReader {

    /**
     * 类的二进制数据
     */
    private byte[] data;

    /**
     * 当前读取到的位置
     */
    private int currentPos = 0;

    public ClassReader(byte[] bytes) {
        this.data = bytes;
    }

    /**
     * 读取 u1
     *
     * @return 字符串
     */
    public byte readU1() {
        return readBytes(1)[0];
    }

    /**
     * 读取 u2
     *
     * @return 字节数组
     */
    public byte[] readU2() {
        return readBytes(2);
    }

    /**
     * 读取 u4
     *
     * @return 字节数组
     */
    public byte[] readU4() {
        return readBytes(4);
    }

    /**
     * 读取 u8
     *
     * @return 字节数组
     */
    public byte[] readU8() {
        return readBytes(8);
    }

    /**
     * 读取 u1
     *
     * @return 无符号字节值
     */
    public short readU1ToUnsignedByte() {
        return UnsignedNumberUtil.toUnsignedByteValue(readU1());
    }

    /**
     * 读取两个字节的 short 类型数据
     * @return 无符号 short 类型数据
     */
    public short readU2ToShort() {
        return ByteUtil.byteToShort(readU2());
    }

    /**
     * 读取两个字节的 short 类型数据
     * @return 无符号 short 类型数据
     */
    public int readU2ToUnsignedShort() {
        return UnsignedNumberUtil.toUnsignedShortValue(ByteUtil.byteToShort(readU2()));
    }

    /**
     * 读取四个字节的 int 类型
     * @return 整型数据
     */
    public int readU4ToInt() {
        return ByteUtil.byteToInt(readU4());
    }

    /**
     * 读取四个字节的 int 整型
     * @return 无符号整型数据
     */
    public long readU4ToUnsignedInt() {
        return UnsignedNumberUtil.toUnsignedIntValue(ByteUtil.byteToInt(readU4()));
    }

    /**
     * 读取 u2 类型 short 数组
     * @return short 数组
     */
    public int[] readU2UnsignedShorts() {
        int num = readU2ToUnsignedShort();
        int[] tmp = new int[num];
        for (int i = 0; i < num; i++) {
            tmp[i] = readU2ToUnsignedShort();
        }
        return tmp;
    }

    /**
     * 读取指定字节
     *
     * @return 16 进制字符串
     */
    public String readString(int number) {
        byte[] bytes = ByteUtil.subBytes(this.data, this.currentPos, number);
        this.currentPos += number;
        return ByteUtil.bytes2HexString(bytes);
    }

    /**
     * 读取指定字节
     *
     * @return 16 进制字符串
     */
    public byte[] readBytes(int number) {
        byte[] bytes = ByteUtil.subBytes(this.data, this.currentPos, number);
        this.currentPos += number;
        return bytes;
    }

}


















